package org.tools.ui.effect
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	
	import mx.containers.ViewStack;
	import mx.controls.Image;
	import mx.core.UIComponent;
	import mx.effects.Move;
	import mx.effects.Parallel;
	import mx.events.EffectEvent;
	import mx.graphics.ImageSnapshot;
	
	import org.tools.ui.rule.ISlideEffectRule;
	
	/**
	 * 两个屏幕滑动替换效果
	 * 只支持ViewStack容器，viewStack应该放在一个父容器中
	 * @author zjm
	 */
	public class SlideEffect
	{
		
		private var parallel:Parallel;
		private var imageMove:Move;
		private var contentMove:Move;
		
		private var viewStack:ViewStack;
		private var animateImage:Image;
		
		private var bitmap:Bitmap;
		private var bitmapData:BitmapData;
		
		private var _effectRule:ISlideEffectRule;
		private var _effectEndFun:Function;
		
		public static const UP:String = 'up';
		public static const DOWN:String = 'down';
		public static const LEFT:String = 'left';
		public static const RIGHT:String = 'right';
		
		public function SlideEffect(_viewStack:ViewStack)
		{
			viewStack = _viewStack;
			
			createAnimateImage(viewStack);
			createEffect();
			
			addShowEffects(viewStack);
		}
		
		public function autoSlide(index:int):void
		{
			var type:String = _effectRule ? _effectRule.getType(index, viewStack.selectedIndex) : SlideEffect.LEFT;
			
			slide(index, type);
		}
		
		public function slide(index:int, slideType:String = SlideEffect.LEFT):void
		{
			var height:Number = viewStack.height;
			var width:Number = viewStack.width;
			
			bitmapData = ImageSnapshot.captureBitmapData(viewStack.selectedChild);
			
			if (!bitmap)
			{
				bitmap = new Bitmap(bitmapData);
			}
			else
			{
				bitmap.bitmapData = bitmapData;
			}
			
			animateImage.width = width;
			animateImage.height = height;
			animateImage.visible = true;
			animateImage.includeInLayout = true;
			animateImage.source = bitmap;
			
			switch (slideType)
			{
				case SlideEffect.UP: 
					move(0, 0, height, 0, 0, 0, 0, -height);
					break;
				case SlideEffect.DOWN: 
					move(0, 0, -height, 0, 0, 0, 0, height);
					break;
				case SlideEffect.LEFT: 
					move(width, 0, 0, 0, 0, -width, 0, 0);
					break;
				case SlideEffect.RIGHT: 
					move(-width, 0, 0, 0, 0, width, 0, 0);
					break;
				default: 
					break;
			}
			
			viewStack.selectedIndex = index;
			contentMove.target = viewStack.selectedChild;
		
		}
		
		private function move(contentXF:int, contentXT:int, contentYF:int, contentYT:int, imageXF:int, imageXT:int, imageYF:int, imageYT:int):void
		{
			contentMove.xFrom = contentXF;
			contentMove.xTo = contentXT;
			contentMove.yFrom = contentYF;
			contentMove.yTo = contentYT;
			
			imageMove.xFrom = imageXF;
			imageMove.xTo = imageXT;
			imageMove.yFrom = imageYF;
			imageMove.yTo = imageYT;
		}
		
		private function createEffect():void
		{
			parallel = new Parallel();
			imageMove = new Move();
			contentMove = new Move();
			
			imageMove.target = this.animateImage;
			
			parallel.addChild(contentMove);
			parallel.addChild(imageMove);
			parallel.addEventListener(EffectEvent.EFFECT_END, effectEndHandler);
		}
		
		/**
		 * 创建image，并将image添加到viewstack的父容器下。image初始化visible=false、includeInLayout=false
		 * @param	viewStack
		 */
		private function createAnimateImage(viewStack:ViewStack):void
		{
			var parentView:DisplayObjectContainer = viewStack.parent;
			
			animateImage = new Image();
			animateImage.visible = false;
			animateImage.includeInLayout = false;
			
			parentView.addChild(animateImage);
		}
		
		private function addShowEffects(viewStack:ViewStack):void
		{
			viewStack.getChildren().forEach(function(child:UIComponent, index:int, arra:Array):void
				{
					child.setStyle('showEffect', parallel);
				});
		}
		
		/**
		 * 动画结束，将快照图片隐藏，并将释放bitmapData资源
		 */
		private function effectEndHandler(event:EffectEvent):void
		{
			_effectEndFun(viewStack.selectedChild)
			animateImage.visible = false;
			animateImage.includeInLayout = false;
			bitmapData.dispose();
			bitmapData = null;
		}
		
		/**
		 * 自定义动画效果规则
		 */
		public function set effectRule(value:ISlideEffectRule):void
		{
			this._effectRule = value;
		}
		
		public function set effectEndFun(value:Function):void
		{
			this._effectEndFun = value;
		}
	}

}

